<?php

include_once('ligature/post.class.php');
include_once('ligature/markdown.php');

class Ligature_Post_model extends Model{
    
    function Ligature_Post_model() {
        parent::Model();
    }
    
    /**
     *  Persist a new Post in the database.
     *  @param Post $post Post
     *  @return Post Object updated with database-generated fields, if applicable.
     */
    function createPost($post) {
        
        $post->setSlug($this->generateSlug($post->getTitle()));
        $post->setDateCreated(time());
        
        // Create Post in data source, assigning identifier if applicable
        $this->db->insert('ligature_post', array(
                'userId'        => $this->session->userdata('current_user_id'),
                'title'         => $post->getTitle(),
                'content'       => $post->getContent(),
                'slug'          => $post->getSlug(),
                'dateCreated'   => $post->getDateCreated()
            ));
        
        // Update identifier field in $post and return, if applicable
        $postId = $this->db->insert_id();
        $post->setPostId($postId);
        
        return $post;
    }

    function createTwitterPost($userId, $post) {
        
        // Create Post in data source, assigning identifier if applicable
        $this->db->insert('ligature_post', array(
                'userId'    => $userId,
                'content'   => $post->getContent(),
                'slug'      => $post->getSlug(),
                'tweetId'   => $post->getTweetId(),
                'dateCreated' => $post->getDateCreated()
            ));
        
    }
    
    function tweetPost($postId, $postAuthorScreenName, $postTitle) {

		$twitter = new EpiTwitter(
                $this->config->item('twitter_consumer_key', 'ligature'),
                $this->config->item('twitter_consumer_secret', 'ligature'),
                $this->session->userdata('oauth_token'),
                $this->session->userdata('oauth_token_secret')
			);
		
        $postShortUrl = ' ' . site_url('p/' . $postId);
		$commentLength = 140 - strlen($postShortUrl);
		
        $tweetContent = $this->clickframes->truncate(
                'New post at ' . $this->config->item('blog_name', 'ligature') . ': ' . $postTitle,
                $commentLength
            );
		
		log_message('debug', '%%%%%%%%%%% ' . $tweetContent . $postShortUrl);
		
		$response = $twitter->post_statusesUpdate(array(
				'status' =>  $tweetContent . $postShortUrl
			));
        
        /*
            We need to store the tweet's ID so we don't display it in the main feed.
        */
        $newTweetId = $response->id;
        $sql = 'INSERT IGNORE INTO ligature_admin_tweet (tweetId) VALUES (?)';
        $this->db->query($sql, array($newTweetId));
        
    }
    
    function generateSlug($title) {
        $slug = preg_replace('/[^a-z0-9-]/', '-', strtolower(trim($title)));
        $slug = preg_replace('/-+/', "-", $slug);
        return $slug;
    }

    /**
     *  Retrieve an Post from the database using its identifier.
     *  @param mixed $id Post's unique identifier
     *  @return Post
     */
    function readPost($id) {
        
        $post = null;

        // Retrieve Post from data source
        $query = $this->db->get_where('ligature_post', array('id' => $id, 'tweetId' => null), 1);

        // Populate $post fields
        if ($query->num_rows() > 0) {
            $row = $query->row();
            $post = new Post(
                    $row->id,
                    null,
                    null,
                    $row->title,
                    $row->content,
                    $row->slug,
                    $row->dateCreated,
                    null,
                    null
                );
        }
        
        return $post;
    }
    
    function getPostSlugFromId($id) {
        $query = $this->db->get_where('ligature_post', array('id' => $id), 1);
        
        $retVal = false;
        
        if ($query->num_rows() > 0) {
            $row = $query->row();
            $retVal = $row->slug;
        }
        
        return $retVal;
    }
    
    /**
     *  Retrieve an Post from the database using its slug.
     *  @param string $slug Post's unique slug
     *  @return Post
     */
    function readPostBySlug($slug) {
        $post = null;
        
        if (!is_null($slug)) {
            // Retrieve Post from data source
            $this->db->select('ligature_post.id, ligature_user.name, ligature_user.twitterScreenName, ligature_post.title, ligature_post.content, ligature_post.dateCreated');
            $this->db->from('ligature_post');
            $this->db->join('ligature_user', 'ligature_post.userId = ligature_user.id');
            $this->db->where('ligature_post.slug', $slug);
            
            $query = $this->db->get();
            
            if ($query->num_rows() == 1) {
                $row = $query->row();
                $post = new Post(
                        $row->id,
                        $row->name,
                        $row->twitterScreenName,
                        $row->title,
                        Markdown($row->content),
                        $slug,
                        $row->dateCreated,
                        $this->clickframes->formatLocalTime($row->dateCreated, $this->config->item('timezone', 'ligature')),
                        null,
                        null
                    );
            }
        }

        return $post;
    }
    
    /**
     *  Retrieve an array of Post objects.
     *  @param integer $page Which batch of results to display
     *  @param integer $perPage Number of Post objects to return in batch, 0 for all
     *  @return array
     */
    function listPost($page = 1, $perPage = 0, $searchTerms = null) {
        $posts = array();
        
        // Retrieve all Posts from data source
        $this->db->select('ligature_post.id, ligature_user.name, ligature_user.twitterScreenName, ligature_post.title, ligature_post.content, ligature_post.slug, ligature_post.dateCreated, ligature_post.tweetId, COUNT(ligature_comment.id) as commentCount');
        $this->db->from('ligature_post');
        $this->db->join('ligature_user', 'ligature_post.userId = ligature_user.id');
        $this->db->join('ligature_comment', 'ligature_comment.postId = ligature_post.id', 'left');
        $this->db->join('ligature_admin_tweet', 'ligature_post.tweetId = ligature_admin_tweet.tweetId', 'left');
        $this->db->where('ligature_admin_tweet.tweetId is null');
        if (!is_null($searchTerms) && strlen(trim($searchTerms)) > 0) {
            $this->db->where('MATCH (ligature_post.title, ligature_post.content) AGAINST ("'.mysql_real_escape_string($searchTerms).'" IN BOOLEAN MODE)', null, false);
        }
        $this->db->group_by(array('ligature_post.id', 'ligature_user.name', 'ligature_user.twitterScreenName', 'ligature_post.title', 'ligature_post.content', 'ligature_post.slug', 'ligature_post.dateCreated', 'ligature_post.tweetId'));
        $this->db->order_by('dateCreated', 'desc');
        if ($perPage > 0) {
            $this->db->limit($perPage, (($page - 1) * $perPage));
        }
        
        $urlPattern = "@\b(https?://)?(([0-9a-zA-Z_!~*'().&=+$%-]+:)?[0-9a-zA-Z_!~*'().&=+$%-]+\@)?(([0-9]{1,3}\.){3}[0-9]{1,3}|([0-9a-zA-Z_!~*'()-]+\.)*([0-9a-zA-Z][0-9a-zA-Z-]{0,61})?[0-9a-zA-Z]\.[a-zA-Z]{2,6})(:[0-9]{1,4})?((/[0-9a-zA-Z_!~*'().;?:\@&=+$,%#-]+)*/?)@";

        $query = $this->db->get();
        // Create and populate Post instances
        foreach ($query->result() as $row) {
            $posts[] = new Post(
                    $row->id,
                    $row->name,
                    $row->twitterScreenName,
                    $row->title,
                    ($row->tweetId == null ? Markdown($row->content) : $this->clickframes->markupTwitterStatus($row->content, false)),
                    $row->slug,
                    $row->dateCreated,
                    $this->clickframes->formatLocalTime($row->dateCreated, $this->config->item('timezone', 'ligature')),
                    $row->commentCount,
                    $row->tweetId);
        }
        return $posts;
    }
    
    function findPost($searchTerms, $page = 1, $perPage = 0) {
        return $this->listPost($page, $perPage, $searchTerms);
    }
    
    function postCount() {
        $this->db->select('COUNT(id) as count');
        $this->db->from('ligature_post');
        $query = $this->db->get();
        $row = $query->row();
        
        return $row->count;
    }
    
    function findCount($searchTerms) {
        $this->db->select('COUNT(id) as count');
        $this->db->where('MATCH (ligature_post.title, ligature_post.content) AGAINST ("'.mysql_real_escape_string($searchTerms).'" IN BOOLEAN MODE)', null, false);
        $this->db->from('ligature_post');
        $query = $this->db->get();
        $row = $query->row();
        
        return $row->count;
    }
    
    /**
     *  Retrieve an array of Post objects which match the provided
     *  search terms.
     *  @param string $searchTerms Search terms to match
     *  @return array
     */
    function searchPost($searchTerms) {
        // TODO: Retrieve all matching Posts from data source
        // TODO: Create and populate Post instances
        return array();        
    }
    
    /**
     *  Update an existing Post in the database. 
     *  @param Post $post The updated object.
     *  @return Post Returns complete post object.
     */
    function updatePost($post) {
        // TODO: Update Post in data source
        $this->db->where('id', $post->getPostId());
        $this->db->update('ligature_post', array(
                'title' => $post->getTitle(),
                'content' => $post->getContent()
            ));
        
        return $this->readPost($post->getPostId());
    }
    
    /**
     *  Delete an Post from the database.
     *  @param mixed $id Unique identifier of Post to delete
     *  @return boolean Returns true if delete successful.
     */
    function deletePost($id) {
        // TODO: Remove Post from data source
        return true;
    }
    
    function loadTwitterPosts() {
        
        $timelines = array();
        $posts = array();
        
        $ids = $this->lastStatusIds($this->config->item('admins', 'ligature'));
        
        foreach ($this->config->item('admins', 'ligature') as $admin) {
            // Pull info from statusIds list
            // Absence from the list indicates that admin does not have user record
            // Admin must log in at least once before Ligature will import his tweets
            if (array_key_exists($admin, $ids)) {
                $statusInfo = $ids[$admin];
                $timeline = $this->getTwitterTimeline($admin, $statusInfo['twitterStatusId']);

                foreach ($timeline as $status) {
                    $post = new Post();
                    $post->setContent($status->text);
                    $post->setDateCreated(strtotime($status->created_at));
                    $post->setSlug('twitter-' . $status->id);
                    $post->setTweetId($status->id);
                    
                    $this->createTwitterPost($statusInfo['ligatureUserId'], $post);
                    $posts[] = $post;
                }
            }
        }
        
        return $posts;
    }
    
    function lastStatusIds($screenNames) {
        
        $this->db->select('ligature_user.id, ligature_user.twitterScreenName');
        $this->db->select_max('ligature_post.tweetId');
        $this->db->from('ligature_user');
        $this->db->join('ligature_post', 'ligature_post.userId = ligature_user.id', 'left');
        $this->db->where_in('ligature_user.twitterScreenName', $screenNames);
        $this->db->group_by('ligature_user.id, ligature_user.twitterScreenName');
        
        $query = $this->db->get();
        
        $ids = array();
        
        foreach ($query->result() as $row) {
            $ids[$row->twitterScreenName] = array('ligatureUserId' => $row->id, 'twitterStatusId' => $row->tweetId);
        }
        
        return $ids;
    }
    
    function getTwitterTimeline($screenName = null, $sinceId = null, $count = 200, $page = null) {
        $twitter = new EpiTwitter();
        
        $params = array();
        
        if (!is_null($screenName)) {
            $params['id'] = $screenName;
        }
        
        if (!is_null($sinceId)) {
            $params['since_id'] = $sinceId;
        }
        
        if (!is_null($count)) {
            $params['count'] = $count;
        }
        
        if (!is_null($page)) {
            $params['page'] = $page;
        }
        
        return $twitter->get_statusesUser_timeline($params);
    }
    
}

/* clickframes::version=3576583151::clickframes */
?>